﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OrderByField = AxeFrog.Data.RepositoryHelper.OrderByField;

namespace AxeFrog.Data
{
	public class SqlSelectStatement
	{
		public string SelectFields { get; set; }
		public string From { get; set; }
		public string Where { get; set; }
		public string OrderBy { get; set; }

		public SqlSelectStatement()
		{
		}

		public SqlSelectStatement Clone()
		{
			return (SqlSelectStatement)MemberwiseClone();
		}

		public SqlSelectStatement(string selectFields, string from, string where, string orderBy)
		{
			SelectFields = selectFields;
			From = from;
			Where = where;
			OrderBy = orderBy;
		}

		public SqlSelectStatement(IEnumerable<string> selectFields, string from, string where, string orderBy)
		{
			if(selectFields == null || selectFields.FirstOrDefault() == null)
				SelectFields = "*";
			else
				SelectFields = selectFields.Concat(", ", s => string.Concat("[", s, "]"));
			From = from;
			Where = where;
			OrderBy = orderBy;
		}

		public SqlSelectStatement(IEnumerable<string> selectFields, string from, string where, IEnumerable<OrderByField> orderBy)
		{
			if(selectFields == null || selectFields.FirstOrDefault() == null)
				SelectFields = "*";
			else
				SelectFields = selectFields.Concat(", ", s => string.Concat("[", s, "]"));
			From = from;
			Where = where;
			if(orderBy != null && orderBy.FirstOrDefault() != null)
				OrderBy = orderBy.Concat(", ", o => string.Concat("[", o.Field, "]", o.Decending ? " DESC" : ""));
		}

		public SqlSelectStatement(IEnumerable<string> selectFields, string from, IEnumerable<string> whereFields, IEnumerable<OrderByField> orderBy)
		{
			if(selectFields == null || selectFields.FirstOrDefault() == null)
				SelectFields = "*";
			else
				SelectFields = selectFields.Concat(", ", s => string.Concat("[", s, "]"));
			From = from;
			if(whereFields != null && whereFields.FirstOrDefault() != null)
				Where = whereFields.Concat(" AND ", f => string.Concat("[", f, "] = @", f));
			if(orderBy != null && orderBy.FirstOrDefault() != null)
				OrderBy = orderBy.Concat(", ", o => string.Concat("[", o.Field, "]", o.Decending ? " DESC" : ""));
		}

		public string Compile(SqlSelectStatementModifications mods)
		{
			StringBuilder sb = new StringBuilder();
			if(!string.IsNullOrEmpty(mods.BeforeSelect))
				sb.Append(mods.BeforeSelect).Append(" ");
			sb.Append("SELECT");
			if(!string.IsNullOrEmpty(mods.AfterSelect))
				sb.Append(" ").Append(mods.AfterSelect).Append(" ");
			sb.Append(" ").Append(string.IsNullOrEmpty(SelectFields) ? "*" : SelectFields).Append(" ");

			if(!string.IsNullOrEmpty(From))
			{
				if(!string.IsNullOrEmpty(mods.BeforeFrom))
					sb.Append(" ").Append(mods.BeforeFrom).Append(" ");
				sb.Append(" FROM ").Append(From);
				if(!string.IsNullOrEmpty(mods.AfterFrom))
					sb.Append(" ").Append(mods.AfterFrom).Append(" ");
			}
			if(!string.IsNullOrEmpty(Where))
			{
				if(!string.IsNullOrEmpty(mods.BeforeWhere))
					sb.Append(" ").Append(mods.BeforeWhere).Append(" ");
				sb.Append(" WHERE ").Append(Where);
				if(!string.IsNullOrEmpty(mods.AfterWhere))
					sb.Append(" ").Append(mods.AfterWhere).Append(" ");
			}
			if(!string.IsNullOrEmpty(OrderBy) && !mods.DisableOrderBy)
			{
				if(!string.IsNullOrEmpty(mods.BeforeOrderBy))
					sb.Append(" ").Append(mods.BeforeOrderBy).Append(" ");
				sb.Append(" ORDER BY ").Append(OrderBy);
				if(!string.IsNullOrEmpty(mods.AfterOrderBy))
					sb.Append(" ").Append(mods.AfterOrderBy).Append(" ");
			}
			if(!string.IsNullOrEmpty(mods.Finish))
				sb.Append(" ").Append(mods.Finish);
			return sb.ToString();
		}

		public string Compile()
		{
			return Compile(new SqlSelectStatementModifications());
		}
	}

	public class SqlSelectStatementModifications
	{
		public string BeforeSelect { get; set; }
		public string AfterSelect { get; set; }
		public string BeforeFrom { get; set; }
		public string AfterFrom { get; set; }
		public string BeforeWhere { get; set; }
		public string AfterWhere { get; set; }
		public string BeforeOrderBy { get; set; }
		public string AfterOrderBy { get; set; }
		public string Finish { get; set; }
		public bool DisableOrderBy { get; set; }
	}
}
